package com.mallcai.bigdata.ladon.dpl.mapper;

import com.mallcai.bigdata.ladon.dpl.entity.BaseEntity;
import com.mallcai.bigdata.ladon.tools.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.jdbc.SQL;
import org.springframework.util.Assert;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author gst
 * @date 2019-12-30 20:36
 */
public abstract class BaseSqlProvider<T extends BaseEntity> {

    /**
     * 获取表名
     *
     * @return String
     */
    public abstract String getTableName();

    /**
     * 获取插入数据的字段列表
     *
     * @return Map
     */
    public abstract Map<String, String> getInsertColumns();

    /**
     * 获取更新操作的字段列表
     *
     * @return Map
     */
    public abstract Map<String, String> getUpdateColumns();

    public String insert(T entity) {
        Map<String, String> columns = getInsertColumns();
        Assert.isTrue(columns != null && columns.size() > 0, "插入字段列表为空");

        // 有三个基础字段
        int intoLen = 3 + columns.size();
        String[] intoColumns = new String[intoLen];
        String[] intoValues = new String[intoLen];
        int index = 0;

        intoColumns[index] = "id";
        // index++ 必须在下面
        intoValues[index++] = "#{id}";

        for (Map.Entry<String, String> entry : columns.entrySet()) {
            intoColumns[index] = entry.getKey();
            intoValues[index] = entry.getValue();
            index++;
        }
        intoColumns[index] = "created";
        // index++ 必须在下面
        intoValues[index++] = "unix_timestamp(now())";

        intoColumns[index] = "created_by";
        // index++ 必须在下面
        intoValues[index] = "#{createdBy}";
        return new SQL() {
            {
                INSERT_INTO(getTableName());
                INTO_COLUMNS(intoColumns);
                INTO_VALUES(intoValues);
            }
        }.toString();
    }

    public String update(T entity) {
        StringBuilder sb = new StringBuilder();
        sb.append("modified = unix_timestamp(now())")
                .append(", modified_by = #{modifiedBy}");
        List<Map<String, Object>> fieldInfos = BeanUtils.getFieldsInfo(entity);
        Map<String, String> field2SqlColumn = getUpdateColumns();

        for (Map<String, Object> map : fieldInfos) {
            if (!map.containsKey("value") ||
                    !map.containsKey("name") ||
                    !map.containsKey("type")) {
                continue; // 说明属性未设置值
            }

            String name = String.valueOf(map.get("name"));

            // 更新属性中不存在,则不做修改
            if (!field2SqlColumn.containsKey(name)) {
                continue;
            }

            // 特殊字段属性不能被修改
            if (StringUtils.equals(name, "id") ||
                    StringUtils.equals(name, "createdBy") ||
                    StringUtils.equals(name, "created")) {
                continue;
            }
            // 属性类型
            String typeClass = String.valueOf(map.get("type"));
            Object value = map.get("value");
            int allowNull = Integer.parseInt(map.get("allowNull").toString());


            if (value == null && allowNull == 0) {
                continue;
            }
            if (StringUtils.equals(typeClass, String.class.getName())) {
                if (allowNull == 0 && StringUtils.isBlank(String.valueOf(value))) {
                    continue;
                }
            }
            sb.append(",").append(field2SqlColumn.get(name)).append("=")
                    .append("#{").append(name).append("}");
        }
        return new SQL() {
            {
                UPDATE(getTableName());
                SET(sb.toString());
                WHERE("id = #{id}");
            }
        }.toString();
    }

    public String delete(T entity) {
        StringBuilder sb = new StringBuilder();
        sb.append("modified = unix_timestamp(now())")
                .append(", modified_by = #{modifiedBy}")
                .append(", archive = 1");

        return new SQL() {
            {
                UPDATE(getTableName());
                SET(sb.toString());
                WHERE("id = #{id}");
            }
        }.toString();
    }

    /**
     * 根据Id查询
     *
     * @param id Long
     * @return String
     */
    public String findById(@Param("id") Long id) {
        return new SQL() {
            {
                SELECT("*");
                FROM(getTableName());
                WHERE("archive = 0 AND id = #{id}");
            }
        }.toString();
    }

    public Map<String, Object> getParams(Map<String, Object> map) {
        Map<String, Object> params = null;
        if (map != null && map.containsKey("params")) {
            Object obj = map.get("params");
            params = (Map<String, Object>) obj;
        }
        if (params == null) {
            params = new HashMap<>(16);
        }

        return params;
    }
}
